package com.nut.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.fasterxml.jackson.databind.JsonNode;
import com.nut.common.RedisKeys;
import com.nut.dto.UserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nut.api.req.WxLoginReq;
import com.nut.api.resp.UserAuth;
import com.nut.common.FailMessage;
import com.nut.interceptor.JwtTokenUtil;
import com.nut.interceptor.UserJwt;
import com.nut.interceptor.UserJwtWx;
import com.nut.service.MemberInviteLogService;
import com.nut.util.IdUtil;
import com.nut.util.InviteCodeUtils;
import com.nut.util.JacksonUtils;
import com.nut.util.RegexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;

import com.nut.common.Result;
import com.nut.entity.Member;
import com.nut.mapper.MemberMapper;
import com.nut.service.MemberService;
import org.springframework.util.StringUtils;

@Service
@Slf4j
public class MemberServiceImpl implements MemberService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private MemberInviteLogService memberInviteLogService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Result<UserAuth> WxLogin(WxLoginReq wxLoginReq, String ip) {
        String code = wxLoginReq.getCode();
        UserInfo userInfo = wxLoginReq.getUserInfo();
        if (code == null || userInfo == null) {
            return Result.fail(FailMessage.BAD_ARGUMENT);
        }

        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = this.wxMaService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
            userInfo.setOpenid(openId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (sessionKey == null || openId == null) {
            log.error("invoke_weixin_fail,code={}", code);
            return Result.fail(FailMessage.WX_INVOKE_FAIL);
        }

        // 邀请人
        Long inviteMemberId = null;
        if (!StringUtils.isEmpty(wxLoginReq.getInviteCode())) {
            inviteMemberId = InviteCodeUtils.codeToId(wxLoginReq.getInviteCode());
        }

        List<Member> users = memberMapper.selectList(new LambdaQueryWrapper<Member>().
                eq(Member::getOpenid, openId));

        String mobile = null;
        Long memberId = null;
        if (users == null || users.size() == 0) {
            //注册新用户
            memberId = IdUtil.getMemberId();

            Member user = new Member();
            user.setId(memberId);
            user.setOpenid(openId);
            user.setSessionkey(sessionKey);
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setStatus(0);
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(ip);
            memberMapper.insert(user);

            // 添加邀请记录
            if (inviteMemberId != null) {
                memberInviteLogService.add(inviteMemberId, memberId);
            }

        } else {

            if (users.size() > 1) {
                log.error("openid_error,openid={}", openId);
                return Result.fail(FailMessage.OPENID_ERROR);
            }

            //更新最后登录信息
            Member member = users.get(0);
            mobile = member.getMobile();
            memberId = member.getId();

            Member user = new Member();
            user.setId(memberId);
            user.setSessionkey(sessionKey);  //更新sessionkey
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(ip);
            int count = memberMapper.updateById(user);
            if (count == 0) {
                return Result.fail(FailMessage.UPDATA_DATA_FAIL);
            }
        }

        if (inviteMemberId != null) {
            //发送津贴
//            memberInviteLogService.sendAllowance(memberId, inviteMemberId);
        }

        UserJwtWx userJwt = new UserJwtWx();
        userJwt.setOpenid(openId);
        userJwt.setMemberId(memberId);
        userJwt.setSessionkey(sessionKey);
        System.out.println("memberId=" + memberId);
        String token = jwtTokenUtil.generateToken(userJwt);
        String inviteCode = InviteCodeUtils.idToCode(memberId);
        UserAuth userAuth = new UserAuth(token, mobile, inviteCode);

        return Result.ok(userAuth);
    }

    @Override
    public Result<String> register(String mobile, String code, Long memberId) {
        log.info("register_req,mobile={},code={},memberId={}", mobile, code, memberId);
        if (StringUtils.isEmpty(mobile)
                || memberId == null || StringUtils.isEmpty(code)) {
            return Result.fail(FailMessage.BAD_ARGUMENT);
        }
        // 检查手机号是否真实
        if (!RegexUtil.isMobileExact(mobile)) {
            log.error("register_mobile_fail,mobile={}", mobile);
            return Result.fail(FailMessage.INVALID_MOBILE);
        }

        Object object = redisTemplate.opsForValue().get(RedisKeys.getSmsMobileKey(mobile));
        if (object == null) {
            return Result.fail(FailMessage.BAD_ARGUMENT);
        }
        // 检查短信验证码是否正确
        if (!object.toString().equals(code)) {
            return Result.fail(FailMessage.WRONG_CODE_ARGUMENT);
        }

        return register(mobile, memberId);
    }

    private Result<String> register(String mobile, Long memberId) {

        // 检查手机号是否已注册
        List<Member> list = memberMapper.selectList(new LambdaQueryWrapper<Member>().
                eq(Member::getMobile, mobile));
        if (list.size() != 0) {
            log.error("mobile_has_registered,mobile={}", mobile);
            return Result.fail(FailMessage.AUTH_MOBILE_REGISTERED);
        }

        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            log.error("member=null,memberId={}", memberId);
            return Result.fail(FailMessage.NOT_FIND_MEMBER);
        }

        Member memberUpdate = new Member();
        memberUpdate.setId(memberId);
        memberUpdate.setMobile(mobile);
        memberMapper.updateById(memberUpdate);

//        ThreadPoolShare.executeTask(() -> {
//            try {
//                //给新用户发送注册优惠券
//                couponService.sendCoupon(memberId, CouponSendTypeEnum.NEW_REGISTER);
//            } catch (Exception e) {
//                e.printStackTrace();
//                log.error("sendToNewRegister_error,memberId=" + memberId);
//            }
//
//            try {
//                //给新用户 赠送200积分
//                sendScore(memberUpdate.getCardno(), 200);
//            } catch (Exception e) {
//                e.printStackTrace();
//                log.error("sendScore_error,memberId=" + memberId);
//            }
//        });
        return Result.ok(mobile);
    }

    @Override
    public Result<String> bindWxMobile(String sessionkey, String data, Long memberId) {
        String mobile = null;
        try {
            //{"errMsg":"getPhoneNumber:fail:user cancel"}
            if (data == null) {
                log.info("data=null,bindWxMobile");
                return Result.fail();
            }
            JsonNode jsonNode = JacksonUtils.toObj(data);
            if (jsonNode.get("encryptedData") == null || jsonNode.get("iv") == null) {
                return Result.fail();
            }

            String encryptedData = jsonNode.get("encryptedData").textValue();
            String iv = jsonNode.get("iv").textValue();

            log.info("encryptedData={},iv={}", encryptedData, iv);

            //获取用户绑定微信的手机号
            WxMaPhoneNumberInfo phoneNumberInfo = this.wxMaService.getUserService().getPhoneNoInfo(sessionkey, encryptedData, iv);
            mobile = phoneNumberInfo.getPhoneNumber();
        } catch (Exception e) {
            log.error("bindMobile_wx_fail,data=" + data);
            e.printStackTrace();
            return Result.fail();
        }

        return register(mobile, memberId);
    }

    @Override
    public Result<IPage<Member>> listPage(Integer pageNo, Integer pageSize) {

//        Page<Member> page = new Page<>(pageNo, pageSize);
//        List<Member> list = memberMapper.listPage(page, 1);
//        page.setRecords(list);
//        return Result.ok(page);
        return Result.ok();
    }

    @Override
    public Result<IPage<Member>> selectPage(String mobile, Integer pageNo, Integer pageSize) {

        Page<Member> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<Member> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(Member::getMobile, mobile);
        queryWrapper.orderByDesc(Member::getId);

        IPage<Member> list = memberMapper.selectPage(page, queryWrapper);
        return Result.ok(list);
    }

    @Override
    public Result<Member> getById(Serializable id) {
        Member member = memberMapper.selectById(id);
        return Result.ok(member);
    }

    @Override
    public Result add(Member member) {
        memberMapper.insert(member);
        return Result.ok();
    }

    @Override
    public Result updateById(Member member) {
        memberMapper.updateById(member);
        return Result.ok();
    }

    @Override
    public Result deleteByIds(Set<Integer> ids) {
        for (Integer id : ids) {
            memberMapper.deleteById(id);
        }
        return Result.ok();
    }
}